#define LOG_TAG "app_main"

#include "string.h"
#include "stdio.h"

#include "app_config.h"
#include "app_main.h"

const uint8_t TX_ADDRESS[TX_ADR_WIDTH] = {0x34, 0x43, 0x10, 0x10, 0x01};   // 发送地址
const uint8_t RX_ADDRESS[RX_ADR_WIDTH] = {0x34, 0x43, 0x10, 0x10, 0x01};   // 接收地址

// 该函数初始化NRF24L01到TX模式
// 设置TX地址,写TX数据宽度,设置RX自动应答的地址,填充TX发送数据,选择RF频道,波特率和LNA HCURR
// PWR_UP,CRC使能
// 当CE变高后,即进入RX模式,并可以发送数据了
const nrf24l0x_reg_init_table_t nrf24l0x_tx_init_table[] = {
    {NRF24L0X_WRITE_REG + EN_AA, 0x01},        // 使能通道0的自动应答
    {NRF24L0X_WRITE_REG + EN_RXADDR, 0x01},    // 使能通道0的接收地址
    {NRF24L0X_WRITE_REG + SETUP_RETR, 0x1a},   // 设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
    {NRF24L0X_WRITE_REG + RF_CH, 40},          // 设置RF通道为40
    {NRF24L0X_WRITE_REG + RF_SETUP, 0x0f},     // 设置TX发射参数,0db增益,2Mbps,低噪声增益开启
    {NRF24L0X_WRITE_REG + CONFIG, 0x0e},       // 配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
};

// 该函数初始化NRF24L01到RX模式
// 设置RX地址,写RX数据宽度,选择RF频道,波特率和LNA HCURR
// 当CE变高后,即进入RX模式,并可以接收数据了
const nrf24l0x_reg_init_table_t nrf24l0x_rx_init_table[] = {
    {NRF24L0X_WRITE_REG + EN_AA, 0x01},                // 使能通道0的自动应答
    {NRF24L0X_WRITE_REG + EN_RXADDR, 0x01},            // 使能通道0的接收地址
    {NRF24L0X_WRITE_REG + RF_CH, 40},                  // 设置RF通信频率
    {NRF24L0X_WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH},   // 选择通道0的有效数据宽度
    {NRF24L0X_WRITE_REG + RF_SETUP, 0x0f},             // 设置TX发射参数,0db增益,2Mbps,低噪声增益开启
    {NRF24L0X_WRITE_REG + CONFIG, 0x0f},               // 配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式

};

int32_t  uart_tx_full_count = 0;
int32_t  uart_tx_half_count = 0;
uint32_t running_seconds    = 0;
uint32_t delay_tick         = 0;

static inline uint32_t clock_time_exceed(uint32_t ref, uint32_t ms)
{
    return ((uint32_t)(HAL_GetTick() - ref) > ms);
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    uart_tx_full_count++;
}

void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
    uart_tx_half_count++;
}

void app_uart_output(const char *log, size_t size)
{
    HAL_UART_Transmit(&huart1, (const uint8_t *)log, (uint16_t)size, HAL_MAX_DELAY);
    // HAL_UART_Transmit_IT(&huart1, (const uint8_t *)log, (uint16_t)size);
    // HAL_UART_Transmit_DMA(&huart1, (const uint8_t *)log, (uint16_t)size);
}

int32_t nrf24l0x_cs_ctrl(uint8_t ctrl)
{
    if (ctrl) {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);
    } else {
        HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);
    }

    return 0;
}
int32_t nrf24l0x_ce_ctrl(uint8_t ctrl)
{
    if (ctrl) {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    } else {
        HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
    }

    return 0;
}

uint8_t nrf24l0x_irq_pin_get(void)
{
    return HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_5);
}

int32_t nrf24l0x_transfer_data(uint8_t *tx_data, uint8_t *rx_data, uint8_t len)
{
    int32_t ret = 0;

    nrf24l0x_cs_ctrl(0);
    ret = HAL_SPI_TransmitReceive(&hspi1, tx_data, rx_data, len, HAL_MAX_DELAY);
    nrf24l0x_cs_ctrl(1);
    // elog_hexdump("transfer:", 16, tx_data, len);
    return ret;
}


int app_init(void)
{
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_SET);

    /* initialize EasyLogger */
    elog_init();
    /* set EasyLogger log format */
    elog_set_fmt(ELOG_LVL_ASSERT, ELOG_FMT_ALL);
    // elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    // elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    // elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG | ELOG_FMT_TIME);
    elog_set_fmt(ELOG_LVL_ERROR, ELOG_FMT_LVL | ELOG_FMT_TAG);
    elog_set_fmt(ELOG_LVL_WARN, ELOG_FMT_LVL | ELOG_FMT_TAG);
    elog_set_fmt(ELOG_LVL_INFO, ELOG_FMT_LVL | ELOG_FMT_TAG);
    elog_set_fmt(ELOG_LVL_DEBUG, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    elog_set_fmt(ELOG_LVL_VERBOSE, ELOG_FMT_ALL & ~(ELOG_FMT_FUNC | ELOG_FMT_T_INFO | ELOG_FMT_P_INFO));
    /* start EasyLogger */
    elog_start();

    log_a("EasyLogger ASSERT!");
    log_e("EasyLogger ERROR!");
    log_w("EasyLogger WARN!");
    log_i("EasyLogger INFO!");
    log_d("EasyLogger DEBUG!");
    log_v("EasyLogger VERBOSE!");

    nrf24l0x_device_t nrf24l0x_dev = {
        .working_mode = NRF24L0X_MODE_RX,
        .rx_addr      = (uint8_t *)&RX_ADDRESS,
        .tx_addr      = (uint8_t *)&TX_ADDRESS,
    };
    nrf24l0x_reg_init_table_t *p_table   = NULL;
    uint8_t                    table_num = 0;
    if (nrf24l0x_dev.working_mode == NRF24L0X_MODE_TX) {
        p_table   = (nrf24l0x_reg_init_table_t *)nrf24l0x_tx_init_table;
        table_num = sizeof(nrf24l0x_tx_init_table) / sizeof(nrf24l0x_tx_init_table[0]);
    } else {
        p_table   = (nrf24l0x_reg_init_table_t *)nrf24l0x_rx_init_table;
        table_num = sizeof(nrf24l0x_rx_init_table) / sizeof(nrf24l0x_rx_init_table[0]);
    }
    nrf24l0x_init(&nrf24l0x_dev, p_table, table_num);

    delay_tick = HAL_GetTick();
    return 0;
}


static uint32_t nrf_tx_count = 0;

void nrf24l0x_test(void)
{
    nrf24l0x_mode_type_e working_mode = nrf24l0x_working_mode_get();

    if (working_mode == NRF24L0X_MODE_RX) {
        uint8_t data[32];
        if (0 == nrf24l0x_rx_packet(data)) {
            elog_hexdump("NRF24L02_ReceivePayload:", 16, data, sizeof(data));
        }

    } else if (working_mode == NRF24L0X_MODE_TX) {
        uint8_t data[32];

        memset(data, 0, sizeof(data));
        sprintf((char *)data, "NRF24L0x TX: %d", nrf_tx_count++);
        nrf24l0x_tx_packet(data);
    }
}

int app_run(void)
{

    if (clock_time_exceed(delay_tick, 1000)) {
        delay_tick = HAL_GetTick();

        running_seconds++;

        nrf24l0x_test();
    }

    return 0;
}
